package zookeeper;

import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkDataListener;

/**
 * 分布式锁具体实现子类
 * zk分布式锁（基于同一个节点，会引发羊群效应）
 */
public class ZookeeperDistributedLock extends ZookeeperAbstractLock {
	
	private static final String lockPath = "/locks"; // lock根节点
	
	private CountDownLatch countDownLatch;

	/**
	 * 子类实现具体的获取分布式锁方法
	 */
	@Override
	boolean tryLock() {
		try {
			zkClient.createEphemeral(lockPath);
			return true;
		} catch (Exception e) {
//			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 子类实现具体的释放分布式锁方法
	 */
	@Override
	void waitLock() {
		// zk监听器
		IZkDataListener iZkDataListener = new IZkDataListener() {
			// 节点被修改
			@Override
			public void handleDataChange(String dataPath, Object data) throws Exception {
				// TODO Auto-generated method stub
				
			}

			// 节点被删除
			@Override
			public void handleDataDeleted(String dataPath) throws Exception {
				if(countDownLatch!=null) {
					countDownLatch.countDown();
				}
			}
		};
		
		// 注册监听器，监听lockPath
		zkClient.subscribeDataChanges(lockPath, iZkDataListener);
		
		if(zkClient.exists(lockPath)) { // 如果lock节点已存在，就创建一个等待信号
			countDownLatch = new CountDownLatch(1);
			try {
				countDownLatch.await(); // 线程会在此等待，直到countDownLatch为0，才继续执行后面的操作
			} catch (Exception e) {
//				e.printStackTrace();
			}
		}
		
		// 监听完成，删除监听事件
		zkClient.unsubscribeDataChanges(lockPath, iZkDataListener);
	}
	
}